using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using DG.Tweening;
using AppEventUtils;
using System;
using TMPro;
using UnityEngine.EventSystems;


public enum CostTypeEnum
{
    mp,
    hp,
}
public enum CardTypeEnum
{
    soldier,
    magic,
}

public enum RoleTypeEnum
{
    None,
    player,
    enemy,
    store_owner,
    temp_player,
    temp_enemy,
}


[Serializable]
public class CardParameter
{
    public CardData card_data;
    
    public Vector3 temperature_position;
    public Vector3 current_position;
    
    public GameObject soldier_obj;
    
    public int ordering;
    public int card_uid;
    
    public RoleTypeEnum belong_to = RoleTypeEnum.None;
    public bool is_in_hand = false;

    public void copy_another_parameter(CardParameter another_parameter)
    {
        this.belong_to = another_parameter.belong_to;
        this.is_in_hand = another_parameter.is_in_hand;
    }
}

public class CardUseInfo
{
    public GameObject creator;
    public List<GameObject> targets;
    public CardEventTypeEnum card_event_type;
}

// public abstract class BaseCardEffectModule: ScriptableObject
public abstract class BaseCardEffectModule
{
    public abstract void Apply(GameObject cardParameter, CardUseInfo useInfo=null);
}

public enum CardEventTypeEnum
{
    OnAppearInStore,
    OnBuy,
    OnGetInHand,
    OnUse,
    OnCreateSoldier,
}


public class CardController: MonoBehaviour
{
    [HideInInspector] public string _recycle_obj_name;
    public string card_obj_name
    {
        get
        {
            if (parameter == null)
                return "card_null";
            string _is_in_hand = parameter.is_in_hand ? "hand" : "place";
            string card_position = $"{parameter.belong_to}, {_is_in_hand}";
            return $"card[{card_position}]_{parameter.ordering}_{card_data.card_name}_{parameter.card_uid}";
        }
    }
    
    public void show_sale_effect_animation()
    {
        create_sale_effect(z: -1f);
        hide_obj();

        var event_i = EventManager.instance.add_animation_event(eventName: $"show_sale_effect_animation", removeWhenRunOnce: true);
        event_i.block = true;
        event_i.event_callback = (sender, args) =>
        {
            float t = 0.1f; // [延迟/等待/休眠/timeout]t秒后执行
            DOTween.To(() => t, (x) => t = x, 0, t).OnComplete(
                () =>
                {
                    GameController.instance.recycle_one_card(this);
                    event_i.finished = true;
                }
            );
            
            return "";
        };
    }
    
    private void Start()
    {
        original_scale = transform.localScale;
        original_z = transform.position.z;
        
        original_scale__card = sub_card_obj.transform.localScale;
        scale_size__waiting_select.z = original_scale.z;
        
        old_taunt_scale = taunt_obj.transform.localScale;
    }

    public void recycle()
    {
        GameController.instance.recycle_one_card(gameObject);
    }

    // public GameObject shield_obj;
    
    public GameObject taunt_obj;
    
    public Animator shield_animator;
    public int be_hurt_times = 0;
    public int be_attack_times = 0;

    public bool is_alive
    {
        get
        {
            return curr_hp > 0;
        }
    }

    private bool _is_active_for_taunt = false;
    private bool _is_changing_taunt_animation = false;
    public bool is_active_for_taunt
    {
        get
        {
            return _is_active_for_taunt;
        }
        set
        {
            _is_active_for_taunt = value;
            btn_activate_taunt(_is_active_for_taunt);
        }
    }

    private Vector3 old_taunt_scale;
    public void btn_activate_taunt(bool is_active = true)
    {
        taunt_obj.SetActive(is_active);

        if (!is_active)
            return;

        if (_is_changing_taunt_animation)
            return;
        _is_changing_taunt_animation = true;

        var target_taunt_scale = old_taunt_scale * 1.2f;
        
        BdPackage.BdUtils.log($"old [{old_taunt_scale}] -> new [{target_taunt_scale}], _is_changing_taunt_animation: {_is_changing_taunt_animation}");
        var event_i = EventManager.instance.add_animation_event(eventName: $"btn_active_shield", removeWhenRunOnce: false);
        event_i.block = false;
        event_i.event_callback = (sender, args) =>
        {
            taunt_obj.transform.DOScale(target_taunt_scale, 0.2f).OnComplete(
                () =>
                {
                    taunt_obj.transform.DOScale(old_taunt_scale, 0.2f);
                    
                    _is_changing_taunt_animation = false;
                    
                    event_i.finished = true;
                });
            return "";
        };
    }
    public void btn_active_shield()
    {
        var event_i = EventManager.instance.add_animation_event(eventName: $"btn_active_shield", removeWhenRunOnce: false);
        event_i.block = false;
        event_i.event_callback = (sender, args) =>
        {
            shield_animator.gameObject.SetActive(false);
            shield_animator.gameObject.SetActive(true);
            
            event_i.finished = true;
            return "";
        };
    }
    
    public void btn_break_shield_animation()
    {
        var event_i = EventManager.instance.add_animation_event(eventName: $"btn_break_shield_animation", removeWhenRunOnce: false);
        event_i.block = true;
        event_i.event_callback = (sender, args) =>
        {
            if (!shield_animator.gameObject.activeSelf)
                shield_animator.gameObject.SetActive(true);
        
            shield_animator.SetTrigger("break");
            
            event_i.finished = true;
            return "";
        };
    }

    public bool is_equal(GameObject target_obj)
    {
        var target_comp = target_obj.GetComponent<CardController>();
        BdPackage.BdUtils.assert(target_comp != null);
        return target_comp.parameter.card_uid == parameter.card_uid;
    }
    
    public bool is_equal(CardController target_comp)
    {
        return target_comp.parameter.card_uid == parameter.card_uid;
    }

    private Vector3 _out_position => GameController.instance._out_position; 

    public void hide_obj()
    {
        deactivate_event_callbacks();
        var event_i = EventManager.instance.add_animation_event(eventName: $"hide_obj", removeWhenRunOnce: true);
        event_i.block = false;
        event_i.event_callback = (sender, args) =>
        {
            // gameObject.transform.DOMove(_out_position, 1f);

            float t = 0.1f; // [延迟/等待/休眠/timeout]t秒后执行
            DOTween.To(() => t, (x) => t = x, 0, t).OnComplete(
                () =>
                {
                    gameObject.transform.position = _out_position;
                }
            );
            event_i.finished = true;
            return "";
        };
        
        // sale_effect.SetActive(false);
        // select_effect.SetActive(false);
        // sub_soldier_obj.SetActive(false);
        // sub_card_obj.SetActive(false);
        // card_ui_obj.SetActive(false);
        // damage_info_effect.SetActive(false);
        // shield_animator.gameObject.SetActive(false);
    }

    public void prepare_recycle()
    {
        // BdPackage.BdUtils.log("--- shield prepare_recycle");

        if (parameter != null && card_data!= null)
            card_data.clear_effect_callbacks();
        
        sale_effect.SetActive(false);
        select_effect.SetActive(false);
        sub_soldier_obj.SetActive(true);
        sub_card_obj.SetActive(false);
        card_ui_obj.SetActive(false);
        damage_info_effect.SetActive(false);
        shield_animator.gameObject.SetActive(false);
        be_attack_times = 0;
        remove_all_event_listener_buff();
    }
    
    public void deactivate_event_callbacks()
    {
        var buff_comp = gameObject.GetComponent<BuffHandle>();
        buff_comp.deactivate_listener_in_event_ls_dc();
    }
    public void activate_event_callbacks()
    {
        var buff_comp = gameObject.GetComponent<BuffHandle>();
        buff_comp.activate_listener_in_event_ls_dc();
    }

    public void remove_all_event_listener_buff()
    {
        var buff_comp = gameObject.GetComponent<BuffHandle>();
        buff_comp.clear_listener_in_event_ls_dc();
    }

    public void add_scale_size_animation_event()
    {
        var event_i = EventManager.instance.add_animation_event(eventName: $"card_scale_size", removeWhenRunOnce: false);
        
        event_i.event_callback = (sender, args) =>
        {
            float do_time = 0.25f;
            transform.DOScale(1.5f, do_time).SetEase(Ease.OutBack).OnComplete(() =>
            {
                transform.DOScale(1f, do_time);
                event_i.finished = true;
            });
            
            return "";
        };
    }
    
    public void btn_hit()
    {
        BdPackage.BdUtils.log($"--- on btn_hit, obj: {this}");
        var damageInfo = new DamageInfo();
        damageInfo.damage = 1;
        damageInfo.creator = gameObject;
        damageInfo.target = gameObject;
        CardDamageManager.instance.SubmitDamage(damageInfo);
    }

    private int current_attack_times = 0;

    public void animation_for_damage(int damage, float duration = 2f, bool scale_text = false)
    {
        if (damage == 0)
            return;
        
        current_attack_times += 1;
        var task_attack_times = current_attack_times;

        int hp = curr_hp;
        var event_i = EventManager.instance.add_animation_event(eventName: $"animation_for_damage", removeWhenRunOnce: true);
        event_i.block = false;
        event_i.event_callback = (sender, args) =>
        {
            if (!gameObject.activeInHierarchy)
                event_i.finished = true;

            hp_text_comp.text = hp.ToString();
            
            if (scale_text)
            {
                float do_time = 0.25f;
                hp_text_comp.transform.DOScale(2f, do_time).SetEase(Ease.OutBack).OnComplete(() =>
                {
                    hp_text_comp.transform.DOScale(1f, do_time);
                });
            }
            
            damage_info_effect.SetActive(false);

            damage_info_text.text = $"-{damage}";

            var particle_comp = damage_info_effect.GetComponentInChildren<ParticleSystem>();
            
            var mainModule = particle_comp.main;
            mainModule.duration = duration;
            mainModule.startLifetime = duration;
            
            damage_info_effect.SetActive(true);

            var initialAlpha = 1f; // 初始透明度
            damage_info_text.color = new Color(
                damage_info_text.color.r,
                damage_info_text.color.g,
                damage_info_text.color.b,
                initialAlpha
            );
            damage_info_text.DOFade(0f, duration) // 持续时间 2 秒，透明度变为 0
                .SetEase(Ease.InExpo); // 使用缓动曲线，前期缓慢，后期快速消失

            float t = duration; // [延迟/等待/休眠/timeout]t秒后执行
            DOTween.To(() => t, (x) => t = x, 0, t).OnComplete(
                () =>
                {
                    if (task_attack_times == current_attack_times)
                    {
                        damage_info_effect.SetActive(false);
                        event_i.finished = true;
                    }
                }
            );
            return null;
        };
    }
    
    public bool IsCanBeKill(DamageInfo damageInfo, bool is_first_run = true)
    {
        // BdPackage.BdUtils.log($"--- on IsCanBeKill: {this}");

        int damage = (int)damageInfo.damage;
        var new_hp = curr_hp - damage;
        
        bool scale_text = damage != 0;
        
        if (new_hp <= 0 && is_first_run)
        {
            return true;
        }

        curr_hp = new_hp;
        float duration = 2f;
        animation_for_damage(damage, duration: duration, scale_text: scale_text);

        if (new_hp <= 0 && !is_first_run)
        {
            float t = 0.1f;  // [延迟/等待/休眠/timeout]t秒后执行
            DOTween.To(() => t, (x) => t = x, 0, t).OnComplete(
                () =>
                {
                    // EventManager.instance.add_blocking_event();
                    
                    var event_i = EventManager.instance.add_animation_event(eventName: $"recycle_card({this})", removeWhenRunOnce: true);
                    // event_i.block = false;
                    event_i.event_callback = (sender, args) =>
                    {
                        if (gameObject.activeInHierarchy)
                        {
                            float change_time = 0.2f;
                            transform.DOScale(scale_size, change_time).OnComplete(
                                () =>
                                {
                                    transform.DOScale(original_scale, change_time).OnComplete(() =>
                                    {
                                        GameController.instance.remove_card_from_selected_place(this, recycle_card: true);
                                        event_i.finished = true;
                                    });
                                }
                            );
                        }
                        return "";
                    };
                    event_i.wait_time = 0.4f;
                }
            );
            
        }
        return false;
    }

    private float original_z;

    private bool _is_frozen = false;

    [HideInInspector]
    public bool is_frozen
    {
        get => _is_frozen;
        set
        {
            if (value != _is_frozen)
            {
                _is_frozen = value;
                frozen_effect.SetActive(_is_frozen);
                if (_is_frozen)
                    change_to_remind_player(0.2f);
            }
        }
    }
    
    public CardParameter parameter = new CardParameter();
    
    public Dictionary<string, OrderedEventList> events = new Dictionary<string, OrderedEventList>();
    
    [HideInInspector] [Header("原始尺寸")] public Vector3 original_scale;
    [HideInInspector] [Header("card原始尺寸")] public Vector3 original_scale__card;

    [Header("缩放尺寸")]
    public Vector3 scale_size = new Vector3(1.5f, 3f, 0.1f);

    [Header("缩放时长")] public float do_time_change = 0.5f;
    
    
    // [Header("悬浮缩放时长")] private float do_time_change__hold = 0.15f;
    
    // [HideInInspector] [Header("悬浮缩放尺寸")]
    [HideInInspector] public Vector3 scale_size__hold = new Vector3(1.2f, 1.2f, 0.1f);
    [HideInInspector] public Vector3 scale_size__waiting_select = new Vector3(1.5f, 1.5f, 0.1f);

    public void change_to_remind_player(float change_time = 0f)
    {
        if (change_time == 0f)
            change_time = do_time_change;
        
        transform.DOScale(scale_size, change_time).OnComplete(
            () =>
            {
                transform.DOScale(original_scale, change_time);
            }
        );
    }

    [HideInInspector] public bool is_waiting_select_flag = false;
    [Header("选中特效")] public GameObject select_effect;
    [Header("伤害效果")] public GameObject damage_info_effect;
    [Header("伤害数字")] public TextMeshPro damage_info_text;
    [Header("卖出特效")] public GameObject sale_effect;
    [Header("冻结特效")] public GameObject frozen_effect;

    public void change_to_waiting_select_state(bool cancel = false, float change_time=0.2f)
    {
        // BdPackage.BdUtils.log($"--- on change_to_waiting_select_state, cancel: {cancel}");

        if (!cancel)
        {
            // select_effect.SetActive(true);
            is_waiting_select_flag = true;
            scale_obj_size(scale_size__waiting_select, top: true, change_time: change_time);
        }
        else
        {
            select_effect.SetActive(false);
            is_waiting_select_flag = false;
            scale_obj_size(original_scale, top: false, change_time: change_time);
        }
    }
    public Tween scaleTween;
    public void scale_obj_size(Vector3 scale_size, bool top = false, float change_time = 0f)
    {
        transform.DOScale(scale_size, change_time);
        // scaleTween = transform.DOScale(scale_size, change_time).OnUpdate(() =>
        // {
        //     if (is_waiting_select_flag)
        //     {
        //         scaleTween.Kill(); // 取消动画
        //     }
        // });
        
        var position = transform.position;
        Vector3 target_pos;
        if (top)
        {;
            target_pos = new Vector3(position.x, position.y, original_z - 2f);
        }
        else
        {
            target_pos = new Vector3(position.x, position.y, original_z);
        }

        transform.position = target_pos;
        
        // if (parameter.belong_to == RoleTypeEnum.player && parameter.is_in_hand == false &&
        //     GameController.instance.is_waiting_select_state)
        // {
        //     BdPackage.BdUtils.log($"--- on scale_obj_size, {gameObject.name},  top: {top}, position: {position}, transform.position: {transform.position}");
        // }
    }
    public void change_to_remind_player__big(bool top = false)
    {
        if (is_waiting_select_flag)
            return;
        
        scale_obj_size(scale_size__hold, top: top);
    }
    public void change_to_remind_player__original(bool top = false)
    {
        if (is_waiting_select_flag)
            return;

        scale_obj_size(original_scale, top: top);
    }

    private TextMeshPro _attack_text_comp;
    public TextMeshPro attack_text_comp
    {
        get
        {
            if (_attack_text_comp == null)
                _attack_text_comp = transform.Find("attack/text").GetComponent<TextMeshPro>();
            return _attack_text_comp;
        }
    }

    private TextMeshPro _hp_text_comp;
    public TextMeshPro hp_text_comp
    {
        get
        {
            if (_hp_text_comp == null)
                _hp_text_comp = transform.Find("hp/text").GetComponent<TextMeshPro>();
            return _hp_text_comp;
        }
    }

    private TextMeshPro _description_text_comp;
    public TextMeshPro description_text_comp
    {
        get
        {
            if (_description_text_comp == null)
                _description_text_comp = sub_card_obj.transform.Find("description/text").GetComponent<TextMeshPro>();
            return _description_text_comp;
        }
    }

    public void update_drag_card_comp_info()
    {
        var drag_card_comp = transform.Find("Canvas/DragUI").GetComponent<DragCard>();
        drag_card_comp.update_card_comp();
    }
    
    private TextMeshPro _name_text_comp;
    public TextMeshPro name_text_comp
    {
        get
        {
            if (_name_text_comp == null)
                _name_text_comp = sub_card_obj.transform.Find("name/text").GetComponent<TextMeshPro>();
            return _name_text_comp;
        }
    }

    private GameObject _sub_soldier_obj;

    public GameObject sub_soldier_obj
    {
        get
        {
            if (_sub_soldier_obj == null)
                _sub_soldier_obj = transform.Find("soldier").gameObject;
            return _sub_soldier_obj;
        }
    }
    
    private GameObject _sub_card_obj;

    public GameObject sub_card_obj
    {
        get
        {
            if (_sub_card_obj == null)
                _sub_card_obj = transform.Find("card").gameObject;
            return _sub_card_obj;
        }
    }
    
    private GameObject _sub_card_stars;
    public GameObject sub_card_stars
    {
        get
        {
            if (_sub_card_stars == null)
            {
                _sub_card_stars = sub_card_obj.transform.Find("Canvas/card_stars").gameObject;
            }
            return _sub_card_stars;
        }
    }
    private GameObject _sub_soldier_stars;
    public GameObject sub_soldier_stars
    {
        get
        {
            if (_sub_soldier_stars == null)
                _sub_soldier_stars = sub_soldier_obj.transform.Find("Canvas/soldier_stars").gameObject;
            return _sub_soldier_stars;
        }
    }

    public void btn_change_to_soldier_state()
    {
        sub_soldier_obj.SetActive(true);
        sub_card_obj.SetActive(false);
    }
    
    public void btn_change_to_card_state()
    {
        sub_soldier_obj.SetActive(false);
        sub_card_obj.SetActive(true);
    }

    public void btn_update_ui_info()
    {
        core_set_info(card_data.attack, card_data.hp, card_data.description, card_data.card_name);
        btn_set_card_star_level();
        btn_set_soldier_star_level();
        GameController.instance.StartCoroutine(core_set_icon());
    }
    
    IEnumerator core_set_icon()
    {
        yield return new WaitForSeconds(0.1f);
        var icon_path = parameter.card_data.icon_path;
        if (BdPackage.BdUtils.conv_to_bool(icon_path))
        {
            // BdPackage.BdUtils.log($"--- on load icon, card: {parameter.card_data.info()}, icon_path: {icon_path}");
            
            // var soldier_icon = BdPackage.BdTools.get_game_object_by_path("soldier/icon", parent: card_obj, raise_error: true);  // 重大bug: 新旧shader会互相影响!!!
            var soldier_icon = gameObject.transform.Find("soldier/icon").gameObject;
            var card_icon = gameObject.transform.Find("card/icon").gameObject;
            
            BdPackage.BdUtils.assert(soldier_icon != null, $"can not find `soldier/icon` in {gameObject.name}");
            BdPackage.BdUtils.assert(card_icon != null, $"can not find `soldier/icon` in {gameObject.name}");
            
            if (!icon_path.StartsWith("Prefabs/Images"))
                icon_path = BdUtils.unity_join("Prefabs/Images", icon_path);
            
            LoadTexture.LoadAndApplyTextureToObj3D(icon_path, soldier_icon, load_from_resources: true);
            yield return new WaitForSeconds(0.01f);
            LoadTexture.LoadAndApplyTextureToObj3D(icon_path, card_icon, load_from_resources: true);
        }
    }

    private Tween atk_scale_tween;
    private Tween hp_scale_tween;

    public void set_current_atk_value(int atk, bool use_do_tween = false)
    {
        if (atk == curr_atk)
            return;
        
        // bool bigger_atk = atk > curr_atk;
        curr_atk = atk;
        attack_text_comp.text = curr_atk.ToString();

        if (use_do_tween)
        {
            float do_time = 0.3f;
            if (is_tween_running(atk_scale_tween))
            {
                atk_scale_tween.Kill();
                attack_text_comp.transform.localScale = 1f * Vector3.one;
            }
            atk_scale_tween = attack_text_comp.transform.DOScale(2f, do_time).SetEase(Ease.OutBack).OnComplete(() =>
            {
                attack_text_comp.transform.DOScale(1f, do_time);
            });
        }
    }
    
    public void set_current_hp_value(int hp, bool use_do_tween = false)
    {
        if (hp == curr_hp)
            return;

        // bool bigger_hp = hp > curr_hp;
        curr_hp = hp;
        hp_text_comp.text = curr_hp.ToString();

        if (use_do_tween)
        {
            scale_hp_text();
        }
    }

    public void scale_hp_text()
    {
        float do_time = 0.3f;
        var event_i = EventManager.instance.add_animation_event(eventName: $"set_current_hp_value", removeWhenRunOnce: true);
        event_i.event_callback = (sender, args) =>
        {
            hp_text_comp.transform.DOScale(2f, do_time).SetEase(Ease.OutBack).OnComplete(() =>
            {
                hp_text_comp.transform.DOScale(1f, do_time);
                
                event_i.finished = true;
            });
            return "";
        };
    }
    
    public void set_current_atk_and_hp_value(int atk, int hp, bool use_do_tween = false)
    {
        set_current_atk_value(atk, use_do_tween: use_do_tween);
        set_current_hp_value(hp, use_do_tween: use_do_tween);
    }
    
    public bool is_tween_running(Tween tween)
    {
        return tween == null || (tween.IsActive() || tween.IsPlaying());
    }
    
    public void core_set_info(int attack, int hp, string description, string name)
    {
        set_current_atk_and_hp_value(attack, hp);
        description_text_comp.text = description;
        name_text_comp.text = name;
    }

    private int MAX_STAR_LEVEL => BaseInfoManager.instance.MAX_STAR_LEVEL;
    
    public void core_set_star_level(int star_level, bool is_card_or_soldier = true)
    {
        // BdPackage.BdUtils.log("--- star_level:", star_level, ", is_card_or_soldier: ", is_card_or_soldier);
        BdPackage.BdUtils.assert(star_level < MAX_STAR_LEVEL, $"*** Error: star_level: {star_level} should less than MAX_STAR_LEVEL: {MAX_STAR_LEVEL}");;
        BdPackage.BdUtils.assert(star_level  >= 1, $"*** Error: star_level: {star_level} should greater than equal 1");;
        GameObject stars = is_card_or_soldier? sub_card_stars : sub_soldier_stars;
        
        for (int i = 0; i < stars.transform.childCount; i++)
        {
            var star_i = stars.transform.GetChild(i).gameObject;
            if (star_i.name == $"star_{star_level}")
            {
                star_i.SetActive(true);
            }
            else
            {
                star_i.SetActive(false);
            }
        }
    }

    public void btn_set_card_star_level(int star_level = -1)
    {
        if (star_level == -1)
            star_level = card_data.star_level;
        core_set_star_level(star_level, is_card_or_soldier: true);
    }
    
    public void btn_set_soldier_star_level(int star_level = -1)
    {
        if (star_level == -1)
            star_level = card_data.star_level;
        core_set_star_level(star_level, is_card_or_soldier: false);
    }

    public void init_card_ui_obj()
    {
        // Destroy(_card_ui_obj);
        card_ui_obj.SetActive(false);
        var card_ui_comp = card_ui_obj.GetComponent<CardController>();
        card_ui_comp.parameter = this.parameter;
        card_ui_comp.btn_change_to_card_state();
        card_ui_comp.btn_update_ui_info();
        // _card_ui_obj = null;
    }
    
    private GameObject _card_ui_obj;

    public GameObject card_ui_obj
    {
        get
        {
            if (_card_ui_obj == null)
            {
                _card_ui_obj = Instantiate(gameObject);
                _card_ui_obj.transform.localScale = gameObject.transform.localScale * 3;
                _card_ui_obj.transform.SetParent(gameObject.transform);
                _card_ui_obj.name = "card_ui_obj";

                var card_ui_comp = _card_ui_obj.GetComponent<CardController>();
                card_ui_comp.btn_change_to_card_state();

                var canvas_obj = _card_ui_obj.transform.Find("Canvas");
                canvas_obj.gameObject.SetActive(false);
                
                card_ui_comp.frozen_effect?.SetActive(false);
            }
            return _card_ui_obj;
        }
    }

    public void btn_show_card_info_ui(bool is_show_card_info_ui = true)
    {
        // BdPackage.BdUtils.log("--- btn_show_card_info_ui:", parameter.card_data.info());
        card_ui_obj.SetActive(is_show_card_info_ui);
        var card_ui_comp = card_ui_obj.GetComponent<CardController>();
        // card_ui_comp.btn_update_ui_info();
        
        card_ui_comp.curr_atk = curr_atk;
        card_ui_comp.curr_hp = curr_hp;
        card_ui_comp.update_atk_and_hp_text();
        
        var position = gameObject.transform.position;

        float width = original_scale__card.x * (3f - 0.5f);
        float height = original_scale__card.y * 3 / 2;
        
        float delta_x = position.x > 0? -width : width;
        float delta_y = position.y > 0? -height : height;
        
        Vector3 position_new = new Vector3(position.x + delta_x, position.y + delta_y, position.z - 1);
        card_ui_obj.transform.position = adjust_position_by_screen_size(position_new, x_range: 0.75f, y_range: 0.5f, is_screen: false);
        
        // BdPackage.BdUtils.log("--- gameObject position:", position);
        // BdPackage.BdUtils.log("--- card_ui_obj position_new:", position_new);
    }
    
    public Vector3 adjust_position_by_screen_size(Vector3 position, float x_range = 0.8f, float y_range = 0.6f, bool is_screen = true)
    {
        if (is_screen)
        {
            float width = Screen.width;
            float height = Screen.height;
            position.x = Mathf.Clamp(position.x, width * (1 - x_range), width * x_range);
            position.y = Mathf.Clamp(position.y, height * (1 - y_range), height * y_range);
        }
        else
        {
            BdPackage.BdUtils.assert(Camera.main.orthographic, "主相机必须为`Orthographic`正交相机模式!");
            float height = Camera.main.orthographicSize;
            float width = height * 2;
            
            position.x = Mathf.Clamp(position.x, -width * x_range, width * x_range);
            position.y = Mathf.Clamp(position.y, -height * y_range, height * y_range);
        }

        return position;
    }
    
    public void OnAppearInStore()
    {
        BdPackage.BdUtils.log("--- OnAppearInStore");
    }
    
    public void OnGetInHand()
    {
        BdPackage.BdUtils.log("--- OnGetInHand");

    }
    
    public void OnBuy()
    {
        BdPackage.BdUtils.log("--- OnBuy");

    }

    public CardData card_data => parameter.card_data;
    public override string ToString()
    {
        if (parameter != null && card_data != null)
            return $"{GetType().Name}->{gameObject.name}->{card_data.card_name} --- [belong_to: {parameter.belong_to}, ordering: {parameter.ordering}, is_in_hand: {parameter.is_in_hand}]";
        else
            return $"{GetType().Name}->{gameObject.name}->card_data: null";
    }
    
    public void OnUse(CardUseInfo card_use_info=null)
    {
        BdPackage.BdUtils.log("--- CardController.OnUse:", this.gameObject.name);
        
        // change_to_remind_player();
        // sale_effect.SetActive(true);
        parameter.card_data.OnUse?.Apply(gameObject, card_use_info);
    }

    public Transform sale_effect_parent_trans => GameController.instance.sale_effect_parent_trans;

    public void _create_sale_effect(float z = -1f)
    {
        var new_obj = ObjectPool.instance.GetObj("sale_effect", prefab: sale_effect);
        new_obj.transform.SetParent(sale_effect_parent_trans);
        // new_obj.transform.position = ScreenPositionTools.set_z_position(sale_effect.transform.position, -1f);
        new_obj.transform.position = sale_effect.transform.position;
        var effect_comp = new_obj.GetComponent<ParticleSystem>();
        set_effect_z_position(effect_comp, z);
        new_obj.transform.localScale = sale_effect.transform.localScale;
        new_obj.transform.rotation = sale_effect.transform.rotation;
        
        // new_obj.SetActive(false);
        new_obj.SetActive(true);
        ObjectPoolManager.instance.recycle_obj(new_obj, 1f);
    }

    public void set_effect_z_position(ParticleSystem effect_comp, float z = 0)
    {
        // 获取粒子系统的 Shape 模块
        var shape = effect_comp.shape;

        // 修改 Shape 的 position 属性
        Vector3 newPosition = shape.position;
        newPosition.z = z; // 设置 Z 轴为 -1
        shape.position = newPosition;

    }

    public void create_sale_effect(float z = -1f, float force_wait_time = 0f)
    {
        var event_i = EventManager.instance.add_animation_event(eventName: $"create_sale_effect", removeWhenRunOnce: true);
        event_i.block = false;
        event_i.force_wait_time = force_wait_time;
        event_i.event_callback = (sender, args) =>
        {
            _create_sale_effect(z);
            
            event_i.finished = true;
            return "";
        };
    }

    // --- 当前hp和atk
    [HideInInspector] public int curr_atk;
    [HideInInspector] public int curr_hp;
    [HideInInspector] public int attack_times = 0;

    public void update_atk_and_hp_text()
    {
        attack_text_comp.text = curr_atk.ToString();
        hp_text_comp.text = curr_hp.ToString();
    }
    
    public void attack_target_obj(GameObject target)
    {
        EventManager.instance.add_blocking_event();
        
        var damage_info_1 = new DamageInfo();
        damage_info_1.damage = curr_atk;
        damage_info_1.target = target;
        damage_info_1.creator = gameObject; 
        
        attack_times += 1;

        animation_for_attack_target_obj(target, block: false);

        var is_killed_target = CardDamageManager.instance.SubmitDamage(damage_info_1);

        var target_comp = target.GetComponent<CardController>(); 
        if (target_comp.curr_atk > 0)
        {
            var damage_info_2 = new DamageInfo();
            damage_info_2.damage = target_comp.curr_atk;
            damage_info_2.target = gameObject;
            damage_info_2.creator = target;
            damage_info_2.active_attack = false;

            var is_killed_creator = CardDamageManager.instance.SubmitDamage(damage_info_2);
        }
        
        EventManager.instance.add_blocking_event();
    }

    private void animation_for_attack_target_obj(GameObject target, bool block = true)
    {
        var event_i = EventManager.instance.add_animation_event(eventName: $"animation_for_attack_target_obj[{target.gameObject.name}]", removeWhenRunOnce: true);
        event_i.block = block;
        event_i.event_callback = (sender, args) =>
        {
            float do_time = 0.2f;
            var origin_position = transform.position;
            transform.DOMove(target.transform.position, do_time).SetEase(Ease.Linear).OnComplete(() =>
            {
                transform.DOMove(origin_position, do_time);
                
                event_i.finished = true;
            });
            return "";
        };
    }

}
